<!DOCTYPE html>
<html>
    <head>
        <!-- Notes: This should be open in its original path-->
        <meta charset="utf-8">
        <meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
        <link rel="stylesheet" href="../script/semantic/semantic.min.css">
        <script src="../script/jquery-3.6.0.min.js"></script>
        <script src="../script/semantic/semantic.min.js"></script>
        <script src="../script/utils.js"></script>
    </head>
    <body>
        <link rel="stylesheet" href="../darktheme.css">
        <script src="../script/darktheme.js"></script>
        <br>
        <div class="ui container">
            <h3 class="ui header">Basic Auth Credential</h3>
            <div class="scrolling content ui form">
                <div id="inlineEditBasicAuthCredentials" class="field">
                    <p>Enter the username and password for allowing them to access this proxy endpoint</p>
                    <table class="ui basic very compacted unstackable celled table">
                        <thead>
                        <tr>
                            <th>Username</th>
                            <th>Password</th>
                            <th>Remove</th>
                        </tr></thead>
                        <tbody id="inlineEditBasicAuthCredentialTable">
                        <tr>
                            <td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td>
                        </tr>
                        </tbody>
                    </table>
                    <div class="three small fields credentialEntry">
                        <div class="field">
                            <input id="inlineEditBasicAuthCredUsername" type="text" placeholder="Username" autocomplete="off">
                        </div>
                        <div class="field">
                            <input id="inlineEditBasicAuthCredPassword" type="password" placeholder="Password" autocomplete="off">
                        </div>
                        <div class="field" >
                            <button class="ui basic button" onclick="addCredentialsToEditingList();"><i class="green add icon"></i> Add Credential</button>
                        </div>
                        <div class="ui divider"></div>
                    </div>
                </div>
            </div>
            <div class="ui divider"></div>
            <h3 class="ui header">Authentication Exclusion</h3>
            <div class="scrolling content ui form">
                <p>Exclude <b>specific directories which contains the following subpath prefix</b> or <b>IP / CIDR</b> from authentication. Useful if you are hosting services require remote API access.</p>
                <table class="ui basic very compacted unstackable celled table">
                    <thead>
                    <tr>
                        <th>Exception Type</th>
                        <th>Path Prefix / CIDR</th>
                        <th>Remove</th>
                    </tr></thead>
                    <tbody id="exclusionPaths">
                    <tr>
                        <td colspan="3"><i class="ui green circle check icon"></i> No Exclusion Rule</td>
                    </tr>
                    </tbody>
                </table>
                <div class="fields" style="margin-bottom: 0.4em;">
                    <div class="field" style="margin-bottom: 0.4em;">
                        <select class="ui basic fluid dropdown" id="exceptionTypeDropdown" style="margin-right: 1em;">
                            <option value="path">Path Prefix</option>
                            <option value="ip">IP / CIDR</option>
                        </select>
                    </div>
                    <div class="field" id="exclusionPathField">
                        <input id="newExclusionPath" type="text" placeholder="/public/api/" autocomplete="off">
                        <small>Make sure you add the trailing slash!</small>
                    </div>
                    <div class="field" id="exclusionIPField" style="display: none;">
                        <input id="newExclusionIP" type="text" placeholder="192.168.1.0/24" autocomplete="off">
                        <small>Enter a valid IP address or CIDR block.</small>
                    </div>
                </div>
                <div class="field" >
                    <button class="ui basic button" onclick="addExceptionPath();"><i class="yellow add icon"></i> Add Exception</button>
                </div>
                <div class="field">
                    <div class="ui basic message">
                        <h4>How to use set excluded paths?</h4>
                        <p>All request URI that contains the given prefix will be allowed to bypass authentication and <b>the prefix must start with a slash.</b> For example, given the following prefix.<br>
                        <code>/public/res/</code><br>
                            <br>
                            Zoraxy will allow authentication bypass of any subdirectories or resources under the /public/res/ directory. For example, the following paths access will be able to bypass basic auth mechanism under this setting.<br>
                            <code>/public/res/photo.png</code><br>
                            <code>/public/res/far/boo/</code></p>
                    </div>
                </div>
            </div>
            
            <br><br><br><br>

        </div>
        <script>
            let editingCredentials = [];
            let editingEndpoint = {};

            if (window.location.hash.length > 1){
                let payloadHash = window.location.hash.substr(1);
                try{
                    payloadHash = JSON.parse(decodeURIComponent(payloadHash));
                    loadBasicAuthCredentials(payloadHash.ep);
                    $("#epname").text(payloadHash.ep);
                    editingEndpoint = payloadHash;
                }catch(ex){
                    console.log("Unable to load endpoint data from hash")
                }
            }
            // Initialize the dropdown
            $('#exceptionTypeDropdown').dropdown({
                onChange: function(value, text, $selectedItem) {
                    if (value === 'ip') {
                        $('#exclusionPathField').hide();
                        $('#exclusionIPField').show();
                    } else {
                        $('#exclusionPathField').show();
                        $('#exclusionIPField').hide();
                    }
                }
            });
            $('#exceptionTypeDropdown').dropdown('set selected', 'path');

            function loadBasicAuthCredentials(uuid){
                $.ajax({
                    url: "/api/proxy/updateCredentials",
                    method: "GET",
                    data: {
                        ep: uuid,
                    },
                    success: function(data){
                        //Push the existing account to list
                        for(var i = 0; i < data.length; i++){
                            // Create a new credential object
                            var credential = {
                                username: data[i],
                                password: ""
                            };

                            // Add the credential to the global credentials array
                            editingCredentials.push(credential);
                        }
                        console.log(data);
                        updateEditingCredentialList();
                    }
                })
            }

            function addCredentialsToEditingList() {
                // Retrieve the username and password input values
                var username = $('#inlineEditBasicAuthCredUsername').val();
                var password = $('#inlineEditBasicAuthCredPassword').val();
                
                if(username == "" || password == ""){
                    parent.msgbox("Username or password cannot be empty", false, 5000);
                    return;
                }

                if (alreadyExists(username)){
                    parent.msgbox("Credential with same username already exists", false, 5000);
                    return;
                }
                
                // Create a new credential object
                var credential = {
                    username: username,
                    password: password
                };

                // Add the credential to the global credentials array
                editingCredentials.push(credential);

                // Clear the input fields
                $('#inlineEditBasicAuthCredUsername').val('');
                $('#inlineEditBasicAuthCredPassword').val('');

                // Update the table body with the credentials
                updateEditingCredentialList();

                //Save the table
                saveCredentials();
            }

            function addExceptionPath(){

                let exceptionType =  $('#exceptionTypeDropdown').val() == "path" ? 0x0 : 0x1;
                let newExclusionPathMatchingPrefix = $('#newExclusionPath').val().trim();
                let newExclusionIP = $('#newExclusionIP').val().trim();
                if (exceptionType == 0x0){
                    //Check if the path is empty
                    
                    if (newExclusionPathMatchingPrefix == ""){
                        parent.msgbox("Matching prefix cannot be empty!", false, 5000);
                        return;
                    }
                }else{
                    //Check if the CIDR is empty
                    if (newExclusionIP == ""){
                        parent.msgbox("Matching CIDR cannot be empty!", false, 5000);
                        return;
                    }
                }
                $.cjax({
                    url: "/api/proxy/auth/exceptions/add",
                    data:{
                        "type":exceptionType,
                        ep: editingEndpoint.ep,
                        prefix: newExclusionPathMatchingPrefix,
                        cidr: newExclusionIP
                    },
                    method: "POST",
                    success: function(data){
                        if (data.error != undefined){
                            parent.msgbox(data.error, false, 5000);
                        }else{
                            initExceptionPaths();
                            parent.msgbox("New exception path added", true);
                            $('#newExclusionPath').val("");
                            $('#newExclusionIP').val("");
                        }
                    }
                });
            }

            function removeExceptionPath(object){
                let matchingPrefix = $(object).attr("prefix");
                let exceptionType = parseInt($(object).attr("etype"));
                if (exceptionType == undefined || matchingPrefix == undefined){
                    parent.msgbox("Invalid exception path data", false, 5000);
                    return;
                }
                
                let reqPayload = {
                    "type": exceptionType,
                    ep: editingEndpoint.ep,
                };

                if (exceptionType == 0x0){
                    reqPayload.prefix = matchingPrefix;
                }else if (exceptionType == 0x1){
                    reqPayload.cidr = matchingPrefix;
                }else{
                    parent.msgbox("Unknown exception type", false, 5000);
                    return;
                }

                $.cjax({
                    url: "/api/proxy/auth/exceptions/delete",
                    data: reqPayload,
                    method: "POST",
                    success: function(data){
                        if (data.error != undefined){
                            parent.msgbox(data.error, false, 5000);
                        }else{
                            initExceptionPaths();
                            parent.msgbox("Exception path removed", true);
                        }
                    }
                });
            }

            function exceptionTypeToString(type){
                switch(type){
                    case 0x0:
                        return "Path Prefix";
                    case 0x1:
                        return "IP or CIDR";
                    default:
                        return "Unknown Type";
                }
            }

            //Load exception paths from server
            function initExceptionPaths(){
                $.get(`/api/proxy/auth/exceptions/list?ptype=${editingEndpoint.ept}&ep=${editingEndpoint.ep}`, function(data){
                    if (data.error != undefined){
                        parent.msgbox(data.error, false, 5000);
                    }else{
                        if (data.length == 0){
                            $("#exclusionPaths").html(` <tr>
                                <td colspan="3"><i class="ui green circle check icon"></i> No Path Excluded</td>
                            </tr>`);
                        }else{
                            $("#exclusionPaths").html("");
                            data.forEach(function(rule){
                                $("#exclusionPaths").append(` <tr>
                                    <td>${exceptionTypeToString(rule.RuleType)}</td>
                                    <td>${rule.PathPrefix || rule.CIDR }</td>
                                    <td><button class="ui red basic mini circular icon button" onclick="removeExceptionPath(this);" etype="${rule.RuleType}" prefix="${rule.PathPrefix || rule.CIDR}"><i class="ui red times icon"></i></button></td>
                                </tr>`);
                            })
                        }   
                    }
                });


            }
            initExceptionPaths();

            function updateEditingCredentialList() {
                var tableBody = $('#inlineEditBasicAuthCredentialTable');
                tableBody.empty();

                if (editingCredentials.length === 0) {
                    tableBody.append('<tr><td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td></tr>');
                } else {
                    for (var i = 0; i < editingCredentials.length; i++) {
                    var credential = editingCredentials[i];
                    var username = credential.username;
                    var password = credential.password.replace(/./g, '*'); // Replace each character with '*'
                    
                    if (credential.password == ""){
                        password = `<span style="color: #c9c9c9;"><i class="eye slash outline icon"></i> Hidden<span>`;
                    }
                    var row = '<tr>' +
                        '<td>' + username + '</td>' +
                        '<td>' + password + '</td>' +
                        '<td><button class="ui basic tiny circular button" onclick="removeCredentialFromEditingList(' + i + ');"><i class="red remove icon"></i> Remove</button></td>' +
                        '</tr>';

                    tableBody.append(row);
                    }
                }
            }

            function removeCredentialFromEditingList(index) {
                // Remove the credential from the credentials array
                editingCredentials.splice(index, 1);

                // Update the table body
                updateEditingCredentialList();
                
                saveCredentials();
            }

            function alreadyExists(username){
                let isExists = false;
                editingCredentials.forEach(function(cred){
                    if (cred.username == username){
                        isExists = true;
                    }
                });
                return isExists;
            }

            function closeThisWrapper(){
                parent.hideSideWrapper(true);
            }

            function saveCredentials(){
                $.cjax({
                    url: "/api/proxy/updateCredentials",
                    method: "POST",
                    data: {
                        ep: editingEndpoint.ep, 
                        creds: JSON.stringify(editingCredentials)
                    },
                    success: function(data){
                        if (data.error != undefined){
                            parent.msgbox(data.error, false, 6000);
                        }else{
                            parent.msgbox("Credentials Updated");
                            //parent.hideSideWrapper(true);
                        }
                    }
                })
            }
        </script>
    </body>
</html>